package main

import (
	"bytes"
	"fmt"
	"html/template"
	"strings"
)

var tpl = `
type {{$.Name}}HTTPServer struct {
	server {{$.Name}}Server
	router gin.IRouter
}

// 实例化这个过程 自动注册
func Register{{$.Name}}HttpServer(server {{$.Name}}Server, router gin.IRouter) {
	//我现在想用gin. Default,如果开发中我想使用其他的方式实例化gin 把权力交给外部
	g := &{{$.Name}}HTTPServer{server: server, router: router}
	g.RegisterService()
}
{{ range .Methods }}
// 然后"生成"这个SayHello 这个_0是为了防止冲突
func (g *{{$.Name}}HTTPServer) {{ .HandlerName }}(c *gin.Context) {
	//入参定义
	var in {{ .Request }}
	//入参
	if err := c.BindJSON(&in); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	//调用生成grpc的方法   尽量松耦合
	//在struct定义这个接口保持松耦合  这样就能通过SayHello转一次
	out, err := g.server.{{ .Name }}(c, &in)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, out)
}
{{ end }}
// 注入路径当中
func (g *{{$.Name}}HTTPServer) RegisterService() {
	//路由映射
{{ range .Methods }}
	g.router.Handle("{{ .Method }}", "{{ .Path }}", g.{{ .HandlerName }})
{{ end }}
}

`

type serviceDesc struct {
	Name    string
	Methods []method
}
type method struct {
	Name    string
	Request string
	Reply   string
	//http rule
	Path   string
	Method string //指的是post还是get等
	Body   string
}

func (m *method) HandlerName() string {
	return m.Name + "_0"
}
func main() {
	//模板
	//缓冲区
	buf := new(bytes.Buffer)
	tmpl, err := template.New("http").Parse(strings.TrimSpace(tpl))
	if err != nil {
		panic(err)
	}
	//模仿
	s := serviceDesc{
		Name: "Greeter",
		Methods: []method{
			{
				Name:    "SayHello",
				Request: "HelloRequest",
				Reply:   "HelloReply",
				Path:    "/v1/sayhello",
				Method:  "POST",
				Body:    "*",
			},
		},
	}
	err = tmpl.Execute(buf, s)
	if err != nil {
		return
	}
	fmt.Println(buf.String())
}
